package sg.edu.nus.iss.billing.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;

import sg.edu.nus.iss.billing.constant.PrivilegeConstants;
import sg.edu.nus.iss.billing.controller.MasterServiceLoader;
import sg.edu.nus.iss.billing.controller.ServiceController;
import sg.edu.nus.iss.billing.entity.service.Service;
import sg.edu.nus.iss.billing.exception.ControllerException;
import sg.edu.nus.iss.billing.gui.component.ErrorDialog;
import sg.edu.nus.iss.billing.gui.subscription.AddSubscriptionPanel;
import sg.edu.nus.iss.billing.gui.subscription.DeregisterSubscriptionPanel;
import sg.edu.nus.iss.billing.gui.subscription.UpdateSubscriptionPanel;
import sg.edu.nus.iss.billing.gui.subscription.ViewSubscriptionPanel;
import sg.edu.nus.iss.billing.localization.MessageKeyManager;
import sg.edu.nus.iss.billing.privilege.AdminRole;
import sg.edu.nus.iss.billing.privilege.AgentRole;
import sg.edu.nus.iss.billing.privilege.User;
import sg.edu.nus.iss.billing.util.Util;

public class MainFrame extends JFrame implements TreeSelectionListener {

	
	private static final long serialVersionUID = 8166256310887657566L;
	public static final int WIDTH = 1000;
	public static final int HEIGHT = 650;
	public static final int WIDTH_MARGIN = 10;
	public static final int HEIGHT_MARGIN = 10;

	private JTree tree;
	private JPanel menuPanel = null;
	private JPanel rightPanel = null;
	private JPanel functionPanel = null;
	private JLabel statusBarLabel;

	public void addUser(User myUser) {
		SessionContext.setUser(myUser);
		init();
	}
	
	public User getUser() {
		return SessionContext.getUser();
	}
	
	public void autoResize() {
		this.pack();
		this.setSize(this.getWidth() + WIDTH_MARGIN, this.getHeight() + HEIGHT_MARGIN);
		this.setLocationRelativeTo(null);
	}

	public MainFrame(String title) {
		super(title);
		setResizable(false);
		SessionContext.setUser(null);
		getContentPane().setLayout(new BorderLayout());
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent we) {
				dispose();
				System.exit(0);
			}
		});
		initData();
		initLogin();
		autoResize();
		setVisible(true);
	}
	
	private void initLogin() {
		getContentPane().removeAll();
		getContentPane().invalidate();
		LoginPanel loginPanel = new LoginPanel(this);
		getContentPane().add(loginPanel, BorderLayout.CENTER);
	}

	private void init() {
		getContentPane().removeAll();
		getContentPane().invalidate();
		if (SessionContext.getUser() != null) {
			this.menuPanel = new JPanel();
			this.tree = new JTree(createTreeNode());
			JScrollPane js = new JScrollPane(this.tree);
			this.tree.addTreeSelectionListener(this);
			js.setPreferredSize(new Dimension((int) (WIDTH * 0.20), HEIGHT));
			this.menuPanel.add(js);

			getContentPane().add(this.menuPanel, BorderLayout.CENTER);
			this.rightPanel = new JPanel();
			this.rightPanel.setLayout(new BorderLayout());

			this.functionPanel = createWelcomePanel();
			this.rightPanel.add(this.functionPanel, BorderLayout.WEST);
			this.rightPanel.setPreferredSize(new Dimension((int) (WIDTH * 0.80),
					HEIGHT));
			getContentPane().add(this.rightPanel, BorderLayout.EAST);
			getContentPane().add(statusBarPanel(), BorderLayout.SOUTH);
		}
		autoResize(); 
		getContentPane().validate();
	}

	public TreeNode createTreeNode() {

		DefaultMutableTreeNode root = new DefaultMutableTreeNode(
				"One# Billing System");

		DefaultMutableTreeNode customer = new DefaultMutableTreeNode(
				"Customers");
		root.add(customer);
		
		
		/* Added by danieltng2002 for Privilege setting for menu access */
		List<MenuFunction> accessibleFunctions = new ArrayList<MenuFunction>();
		if (SessionContext.getUser() != null && SessionContext.getUser().getRole() != null) {
			accessibleFunctions = SessionContext.getUser().getRole().getFunctionList();
		}
		
		MenuFunction [] customerFunctions = 
		{new MenuFunction(PrivilegeConstants.VIEW_CUST_FUNC), 
		 new MenuFunction(PrivilegeConstants.UPDATE_CUST_FUNC),
		 new MenuFunction(PrivilegeConstants.ADD_CUST_FUNC),
		 new MenuFunction(PrivilegeConstants.DEREG_CUST_FUNC)};

		for (int i = 0; i < customerFunctions.length; i++) {
			if (accessibleFunctions.contains(customerFunctions[i])) {
				customer.add(new DefaultMutableTreeNode(customerFunctions[i]));
			}
		}
		
		DefaultMutableTreeNode subsciptions = new DefaultMutableTreeNode(
				"Subscriptions");
		root.add(subsciptions);
		MenuFunction subsciptionFunctions[] = 
		{new MenuFunction(PrivilegeConstants.VIEW_SUBS_FUNC),
		 new MenuFunction(PrivilegeConstants.UPDATE_SUBS_FUNC), 
		 new MenuFunction(PrivilegeConstants.ADD_SUBS_FUNC),
		 new MenuFunction(PrivilegeConstants.DEREG_SUBS_FUNC) };
		for (int i = 0; i < subsciptionFunctions.length; i++) {
			if (accessibleFunctions.contains(subsciptionFunctions[i])) {
				subsciptions.add(new DefaultMutableTreeNode(subsciptionFunctions[i]));
			}
		}

		DefaultMutableTreeNode complaints = new DefaultMutableTreeNode(
				"Complaints");
		root.add(complaints);
		MenuFunction complaintsFunctions[] = 
		{new MenuFunction(PrivilegeConstants.VIEW_COMPLAINT_FUNC), 
		 //new MenuFunction(PrivilegeConstants.UPDATE_COMPLAINT_FUNC),
		 new MenuFunction(PrivilegeConstants.LOG_COMPLAINT_FUNC)};
		for (int i = 0; i < complaintsFunctions.length; i++) {
			if (accessibleFunctions.contains(complaintsFunctions[i])) {
				complaints.add(new DefaultMutableTreeNode(complaintsFunctions[i]));
			}
		}

		DefaultMutableTreeNode bills = new DefaultMutableTreeNode("Bills");
		root.add(bills);
		MenuFunction billsFunctions[] = 
		{new MenuFunction(PrivilegeConstants.VIEW_BILL_FUNC), 
		 new MenuFunction(PrivilegeConstants.GENERATE_BILL_FUNC)};
		for (int i = 0; i < billsFunctions.length; i++) {
			if (accessibleFunctions.contains(billsFunctions[i])) {
				bills.add(new DefaultMutableTreeNode(billsFunctions[i]));
			}
		}
		
		DefaultMutableTreeNode sysAdmin = new DefaultMutableTreeNode("System Admin");
		root.add(sysAdmin);
		MenuFunction sysMenuFunctions[] =
		{new MenuFunction(PrivilegeConstants.ADD_USER_FUNC),
		 new MenuFunction(PrivilegeConstants.UPDATE_USER_FUNC)
		};
		for (int i = 0; i < sysMenuFunctions.length; i++) {
			if (accessibleFunctions.contains(sysMenuFunctions[i])) {
				sysAdmin.add(new DefaultMutableTreeNode(sysMenuFunctions[i]));
			}
		}
		/* End Added */
		root.add(new DefaultMutableTreeNode(new MenuFunction(PrivilegeConstants.LOGOUT_FUNC)));
		
		return root;

	}

	public JPanel statusBarPanel() {
		JPanel statusBarPanel = new JPanel();
		statusBarPanel.setLayout(new BorderLayout());
		statusBarPanel.setPreferredSize(new Dimension(106, 20));
		this.statusBarLabel = new JLabel("READY");
		statusBarPanel.add(this.statusBarLabel, BorderLayout.NORTH);
		return statusBarPanel;
	}

	public JPanel createWelcomePanel() {

		JPanel welcomePanel = new JPanel();
		welcomePanel.setLayout(null);
		welcomePanel.setPreferredSize(new Dimension(800, 600));

		JLabel custLabel = new JLabel();
		if (SessionContext.getUser().getRole().getClass() == AdminRole.class) {
		    custLabel = new JLabel("You are log in as an Administrator");
		} else if (SessionContext.getUser().getRole().getClass() == AgentRole.class) {
		    custLabel = new JLabel("You are log in as an Call Agent");
		}
		custLabel.setBounds(300, 300, 200, 20);
		welcomePanel.add(custLabel);
		return welcomePanel;
	}

	public JPanel createActionButtonsPanel() {

		JPanel p = new JPanel(new FlowLayout());
		p.add(new JButton("ADD"));
		p.add(new JButton("CANCEL"));
		return p;
	}

	@Override
	public void valueChanged(TreeSelectionEvent arg0) {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) this.tree
				.getLastSelectedPathComponent();
		if (node == null)
			return;
		String menuName = node.toString();
		Object menuObject = node.getUserObject();
		MenuFunction selectedFunction = null;
		if (menuObject instanceof MenuFunction) {
			selectedFunction = (MenuFunction)menuObject;
			if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.ADD_USER_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new AddEditUserPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.ADD_CUST_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new AddCustomerPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.UPDATE_CUST_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new UpdateCustomerPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.UPDATE_USER_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new UpdateUserPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.VIEW_COMPLAINT_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new ViewComplaintPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} 
/*
			// update functionality built into the view screen
			else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.UPDATE_COMPLAINT_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new UpdateComplaintPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} 
*/
			else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.LOG_COMPLAINT_FUNC)) {
				this.rightPanel.remove(this.functionPanel);
				this.functionPanel = new LogComplaintPanel();
				this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.VIEW_CUST_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new ViewCustomerPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);			    
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.DEREG_CUST_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new DeregisterCustomerPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.VIEW_BILL_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new ViewBillPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.GENERATE_BILL_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new GenerateBillPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			}else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.VIEW_SUBS_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new ViewSubscriptionPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.ADD_SUBS_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new AddSubscriptionPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			} else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.DEREG_SUBS_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new DeregisterSubscriptionPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			}else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.UPDATE_SUBS_FUNC)) {
                this.rightPanel.remove(this.functionPanel);
                this.functionPanel = new UpdateSubscriptionPanel();
                this.rightPanel.add(this.functionPanel, BorderLayout.NORTH);
			}else if (selectedFunction.getFunctionKey().equals(PrivilegeConstants.LOGOUT_FUNC)) {
				doLogout();
			}
			
		this.statusBarLabel.setText(menuName);
		this.functionPanel.revalidate();
		return;
		}
	}
	
	private void doLogout(){
		int opt= JOptionPane.showConfirmDialog(null, MessageKeyManager.getMessage("msg.logOut"));
		if (opt == JOptionPane.YES_OPTION){
			dispose();
			System.exit(0);
		}else{
			tree.setSelectionPath(tree.getLeadSelectionPath());
		}
	}
	
	private void initData(){
		ServiceController svcCtl = new ServiceController();
		try {
			List<Service> list = svcCtl.getAllServices();
			if(Util.isEmpty(list)){
				MasterServiceLoader.loadServices();
			}
		} catch (ControllerException e) {
			ErrorDialog.showControllerErrorMessageDialog(e);
		}
		
	}
	
	public static void main(String[] argv) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				MainFrame myExample = new MainFrame("One# Billing System");
				myExample.setLocationRelativeTo(null);
				myExample.setVisible(true);
			}
		});
	}

}
